<!--
 * @Author: yanjikun
 * @Date: 2022-05-12 11:45:25
 * @LastEditors: yanjikun
 * @LastEditTime: 2022-05-12 17:59:58
 * @Description: file content
-->
<script lang="tsx">
  import { getSlot } from '@/hooks/helper/tsxHelper'
  import { Descriptions } from 'ant-design-vue'
  import { get, isBoolean, isFunction, set } from 'lodash'
  import { computed, defineComponent, ref, unref } from 'vue'
  import { BasicDescriptionsProps, basicDescriptionsProps } from './basic-descriptions'
  import { DescriptionsConfig } from './types/descriptions'

  export default defineComponent({
    name: 'BasicDescriptions',
    props: basicDescriptionsProps,
    setup(props, { slots, attrs, expose }) {
      const propsRef = ref<Partial<BasicDescriptionsProps> | null>(null)
      const getProps = computed(() => {
        return { ...props, ...attrs, ...unref(propsRef) }
      })
      const defaultSlots = ['title', 'extra']
      const renderLabel = (configItem: DescriptionsConfig) => {
        const { label, labelStyle } = configItem
        if (!labelStyle) {
          return label
        }
        return <div style={labelStyle}>{label}</div>
      }
      const getShow = (configItem: DescriptionsConfig) => {
        const { show, field } = configItem
        const { fields } = unref(getProps)
        if (isBoolean(show)) {
          return show
        }
        if (isFunction(show)) {
          return show({ value: fields[field] ?? '', fields })
        }
        return true
      }
      const renderItem = () => {
        const { config, fields } = unref(getProps)
        return config.map((item) => {
          if (!getShow(item)) {
            return null
          }
          const { field, bodyCell, slot, span } = item
          const getContent = () => {
            const getField = get(fields, field, '')
            const callbackParams = { value: getField, fields }
            if (slot) {
              return getSlot(slots, slot, callbackParams)
            }
            return isFunction(bodyCell) ? bodyCell(callbackParams) : getField
          }
          return (
            <Descriptions.Item label={renderLabel(item)} span={span} key={field}>
              {getContent()}
            </Descriptions.Item>
          )
        })
      }
      const renderSlots = () => {
        return defaultSlots.reduce((prev, slot) => {
          return set(prev, slot, () => getSlot(slots, slot))
        }, {})
      }
      const setProps = (props: Partial<BasicDescriptionsProps>) => {
        propsRef.value = { ...unref(propsRef), ...props }
      }
      expose({ setProps })
      return () => (
        <Descriptions {...unref(getProps)}>
          {{ default: () => renderItem(), ...renderSlots() }}
        </Descriptions>
      )
    },
  })
</script>

<style scoped lang="less"></style>
